/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.gallsoft.amidar;

import android.graphics.Point;

import com.gallsoft.amidar.GameObject.ActionType;
import com.gallsoft.amidar.HotSpotSystem;
import com.gallsoft.amidar.HotSpotSystem.HotSpotType;

public class PlayerComponent extends GameComponent {
    private static final float GROUND_IMPULSE_SPEED = 5000.0f;
    private static final float MAX_GROUND_HORIZONTAL_SPEED = 200.0f;
    private static final float HIT_REACT_TIME = 0.5f;   
    public static final int MAX_PLAYER_LIFE = 3;
    
    public enum State {
        MOVE,
        DEAD,
        WIN
    }
    
    private State mState;
    private float mTimer;
    private float mTimer2;
    private int availDir, newAvailDir, currentDir;
    private boolean atJunction;
    private Point nextDotCoords = new Point();
    private Point nextDotArray = new Point();
    
    public PlayerComponent() {
        super();
        reset();
        setPhase(ComponentPhases.THINK.ordinal());
    }
    
    @Override
    public void reset() {
        mState = State.MOVE;
        mTimer = 0.0f;
        mTimer2 = 0.0f;
        availDir = HotSpotType.GO_LEFT | HotSpotType.GO_RIGHT;
        atJunction = false;
        currentDir = HotSpotType.GO_LEFT;
        nextDotCoords.set(153, 148);
        nextDotArray.set(12, 26);
    }

    protected void move(float time, float timeDelta, GameObject parentObject) {
        VectorPool pool = sSystemRegistry.vectorPool;
        InputGameInterface input = sSystemRegistry.inputGameInterface;
        Vector2 impulse = pool.allocate();
        
        if (pool != null && input != null) {
            final InputXY dpad = input.getDirectionalPad();
            final InputButton jumpButton = input.getJumpButton();
            int newDir = 0;
            
            HotSpotSystem hotSpot = sSystemRegistry.hotSpotSystem;
            int dirs = hotSpot.getHotSpot(parentObject.getPosition(), newDir);
		
            if (!atJunction && dirs > 0) {
        		availDir = dirs;
        		atJunction = true;
            }
            else if (dirs == 0)
            	atJunction = false;
            
            if (dpad.getPressed() || jumpButton.getPressed()) {                
                if (dpad.getPressed()) {
                    parentObject.setCurrentAction(ActionType.IDLE);
                	
                	if (dpad.getX() > 0.0f) { // Move right
                		if ((availDir & HotSpotType.GO_RIGHT) == HotSpotType.GO_RIGHT) {             		
	                		parentObject.setCurrentAction(ActionType.MOVE_HORIZ);
	                		newDir = newDir | HotSpotType.GO_RIGHT;
                		}
                		
                	}
                	else if (dpad.getX() < 0.0f) { // Move left
                		if ((availDir & HotSpotType.GO_LEFT) == HotSpotType.GO_LEFT) {             		
	                		parentObject.setCurrentAction(ActionType.MOVE_HORIZ);
	                		newDir = newDir | HotSpotType.GO_LEFT;
                		}
                		
                	}
                	
                	if (dpad.getY() > 0.0f) { // Move down
                		if ((availDir & HotSpotType.GO_DOWN) == HotSpotType.GO_DOWN) {             		
	                		parentObject.setCurrentAction(ActionType.MOVE_VERT);
	                		newDir = newDir | HotSpotType.GO_DOWN;
                		}
                		
                	}
                	else if (dpad.getY() < 0.0f) { // Move up
                		if ((availDir & HotSpotType.GO_UP) == HotSpotType.GO_UP) {             		
                			parentObject.setCurrentAction(ActionType.MOVE_VERT);
                			newDir = newDir | HotSpotType.GO_UP;
                		}           			
                	}
                	
                	//******************************
                	// Read multiple D-Pad controls
                	//******************************
                	if ((currentDir & (HotSpotType.GO_LEFT | HotSpotType.GO_RIGHT)) > 0) {
                		if ((newDir & HotSpotType.GO_UP) == HotSpotType.GO_UP) {
                			parentObject.setPosition(hotSpot.getLastJunction());
                			impulse.set(0.0f, 80.0f);
                			currentDir = HotSpotType.GO_UP;
                			availDir = HotSpotType.GO_UP | HotSpotType.GO_DOWN;
                		}
                		else if ((newDir & HotSpotType.GO_DOWN) == HotSpotType.GO_DOWN) {
                			parentObject.setPosition(hotSpot.getLastJunction());
                			impulse.set(0.0f, -80.0f);
                			currentDir = HotSpotType.GO_DOWN;
                			availDir = HotSpotType.GO_UP | HotSpotType.GO_DOWN;
                		}
                   		else if ((newDir & HotSpotType.GO_LEFT) == HotSpotType.GO_LEFT) {
                			impulse.set(-70.0f, 0.0f);
                			currentDir = HotSpotType.GO_LEFT;
                			availDir = HotSpotType.GO_LEFT | HotSpotType.GO_RIGHT;
                		}
                   		else if ((newDir & HotSpotType.GO_RIGHT) == HotSpotType.GO_RIGHT) {
                			impulse.set(70.0f, 0.0f);
                			currentDir = HotSpotType.GO_RIGHT;
                			availDir = HotSpotType.GO_LEFT | HotSpotType.GO_RIGHT;
                		}
                	}
                	else if ((currentDir & (HotSpotType.GO_UP | HotSpotType.GO_DOWN)) > 0) {
                		if ((newDir & HotSpotType.GO_RIGHT) == HotSpotType.GO_RIGHT) {
                			parentObject.setPosition(hotSpot.getLastJunction());
                			impulse.set(70.0f, 0.0f);
                			currentDir = HotSpotType.GO_RIGHT;
                			availDir = HotSpotType.GO_RIGHT | HotSpotType.GO_LEFT;
                		}
                		else if ((newDir & HotSpotType.GO_LEFT) == HotSpotType.GO_LEFT) {
                			parentObject.setPosition(hotSpot.getLastJunction());
                			impulse.set(-70.0f, 0.0f);
                			currentDir = HotSpotType.GO_LEFT;
                			availDir = HotSpotType.GO_RIGHT | HotSpotType.GO_LEFT;
                		}
                		else if ((newDir & HotSpotType.GO_UP) == HotSpotType.GO_UP) {
                			impulse.set(0.0f, 80.0f);
                			currentDir = HotSpotType.GO_UP;
                			availDir = HotSpotType.GO_UP | HotSpotType.GO_DOWN;
                		}
                		else if ((newDir & HotSpotType.GO_DOWN) == HotSpotType.GO_DOWN) {
                			impulse.set(0.0f, -80.0f);
                			currentDir = HotSpotType.GO_DOWN;
                			availDir = HotSpotType.GO_UP | HotSpotType.GO_DOWN;
                		}
                	}
                	
                }                
                                
                if (jumpButton.getPressed()) {
                }                
            }
            else
            	parentObject.setCurrentAction(ActionType.IDLE);

        }
        else
        	impulse.set(0.0f, 0.0f);
        
        parentObject.getVelocity().set(impulse);
        parentObject.getImpulse().set(0.0f, 0.0f);
        pool.release(impulse);
    }
    
    public void update(float timeDelta, BaseObject parent) {

        TimeSystem time = sSystemRegistry.timeSystem;
        GameObject parentObject = (GameObject)parent;
        
        if (parentObject.getCurrentAction() == ActionType.INVALID) {
            gotoMove(parentObject);
        }

        final float gameTime = time.getGameTime();
     // Watch for hit reactions or death interrupting the state machine.
        if (mState != State.DEAD && mState != State.WIN ) {
            if (parentObject.life <= 0) {
                gotoDead(gameTime);
            } 
        }
        
        switch(mState) {
            case MOVE: 
                stateMove(gameTime, timeDelta, parentObject);
                break;
            case DEAD:
                stateDead(gameTime, timeDelta, parentObject);
                break;
            case WIN:
                stateWin(gameTime, timeDelta, parentObject);
                break;
            default:
                break;
        }
        
        //final HudSystem hud = sSystemRegistry.hudSystem;
        final InputGameInterface input = sSystemRegistry.inputGameInterface;
        
        //if (hud != null) {
        //    hud.setFuelPercent(mFuel / FUEL_AMOUNT);
        //    hud.setButtonState(input.getJumpButton().getPressed(), input.getAttackButton().getPressed());
        //}
    
    }
    
    protected void gotoMove(GameObject parentObject) {
        parentObject.setCurrentAction(GameObject.ActionType.MOVE_HORIZ);
        mState = State.MOVE;
    }
    
    protected void stateMove(float time, float timeDelta, GameObject parentObject) {
    	move(time, timeDelta, parentObject);
    }
    
    protected void gotoHitReact(GameObject parentObject, float time) {
    }
    
    protected void stateHitReact(float time, float timeDelta, GameObject parentObject) {
        // This state just waits until the timer is expired.
        if (time - mTimer > HIT_REACT_TIME) {
            gotoMove(parentObject);
        }
    }
    
    protected void gotoDead(float time) {
        mState = State.DEAD;
        mTimer = time;
    }
    
    protected void stateDead(float time, float timeDelta, GameObject parentObject) {
    }
    
    protected void gotoWin(float time) {
        mState = State.WIN;
        TimeSystem timeSystem = sSystemRegistry.timeSystem;
        mTimer = timeSystem.getRealTime();
        timeSystem.appyScale(0.1f, 8.0f, true);
    }
    
    protected void stateWin(float time, float timeDelta, GameObject parentObject) {
       if (mTimer > 0.0f) {
        	TimeSystem timeSystem = sSystemRegistry.timeSystem;
            final float elapsed = timeSystem.getRealTime() - mTimer;
            
            /*
            HudSystem hud = sSystemRegistry.hudSystem;
            
            if (hud != null && !hud.isFading()) {
                if (elapsed > 2.0f) {
                    hud.startFade(false, 1.5f);
                    hud.sendGameEventOnFadeComplete(GameFlowEvent.EVENT_GO_TO_NEXT_LEVEL, 0);

                }
            }
            */
        }
    }    
}